package com.test.registry;

import com.test.bean.DisposableBean;
import com.test.exception.BeansException;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * 默认的单例注册实现类
 * 使用HashMap来存储单例对象，保证线程安全
 */
public class DefaultSingletonRegistry implements SingletonBeanRegistry {

    // 存储单例对象的容器
    private final Map<String, Object> singletonObjects = new HashMap<>();

    // 使用LinkedHashMap来保持插入顺序，便于后续按照注册的相反顺序销毁bean
    private final Map<String, DisposableBean> disposableBeans = new LinkedHashMap<>();

    /**
     * 注册需要销毁的bean
     *
     * @param beanName bean的名称，用于标识bean
     * @param bean 需要销毁的bean实例
     */
    public void registerDisposableBean(String beanName, DisposableBean bean) {
        disposableBeans.put(beanName, bean);
    }

    /**
     * 销毁单例bean
     * 本方法按照注册的相反顺序来销毁bean，以确保依赖关系被正确处理
     */
    public void destroySingletons() {
        // 获取所有bean的名称
        Set<String> beanNames = this.disposableBeans.keySet();
        // 将bean名称转换为数组，以便按照注册的相反顺序遍历
        String[] disposableBeanNames = beanNames.toArray(new String[0]);

        // 按照注册的相反顺序销毁bean
        for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
            String beanName = disposableBeanNames[i];
            // 从map中移除对应的bean
            DisposableBean disposableBean = disposableBeans.remove(beanName);
            try {
                // 调用bean的销毁方法
                disposableBean.destroy();
            } catch (Exception e) {
                // 如果销毁过程中抛出异常，则包装并抛出自定义异常
                throw new BeansException("销毁bean [" + beanName + "] 失败", e);
            }
        }
    }


    /**
     * 获取已注册的单例对象
     *
     * @param beanName 单例对象的名称
     * @return 返回单例对象，如果未找到则返回null
     */
    @Override
    public Object getSingleton(String beanName) {
        return singletonObjects.get(beanName);
    }

    /**
     * 注册单例对象
     *
     * @param beanName 单例对象的名称
     * @param singletonObject 单例对象的实例
     * @throws IllegalStateException 如果单例对象已存在，则抛出此异常
     */
    @Override
    public void registrySingleton(String beanName, Object singletonObject) {
        if (singletonObjects.containsKey(beanName)) {
            throw new IllegalStateException("名为 '" + beanName + "' 的单例bean已经存在");
        }
        singletonObjects.put(beanName, singletonObject);
    }

    /**
     * 检查是否包含指定名称的单例对象
     *
     * @param beanName 单例对象的名称
     * @return 如果包含则返回true，否则返回false
     */
    protected boolean containsSingleton(String beanName) {
        return singletonObjects.containsKey(beanName);
    }

    /**
     * 获取所有单例对象的名称
     *
     * @return 返回包含所有单例对象名称的数组
     */
    protected String[] getSingletonNames() {
        return singletonObjects.keySet().toArray(new String[0]);
    }

    /**
     * 获取单例对象的数量
     *
     * @return 返回单例对象的数量
     */
    protected int getSingletonCount() {
        return singletonObjects.size();
    }
}
